﻿using AutoMapper;
using DTcms.Core.Common.Emum;
using DTcms.Core.Common.Extensions;
using DTcms.Core.Common.Helper;
using DTcms.Core.DBFactory.Database;
using DTcms.Core.IServices;
using DTcms.Core.Model.Models;
using DTcms.Core.Model.ViewModels;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;

namespace DTcms.Core.Services
{
    /// <summary>
    /// 支付收款接口实现
    /// </summary>
    public class PaymentCollectionService : BaseService, IPaymentCollectionService
    {
        private readonly IUserService _userService;
        private readonly IMapper _mapper;

        public PaymentCollectionService(IDbContextFactory contentFactory,
            IUserService userService, IMapper mapper) : base(contentFactory)
        {
            _userService = userService;
            _mapper = mapper;
        }

        /// <summary>
        /// 查询一条记录
        /// </summary>
        public async Task<PaymentCollection?> QueryAsync(Expression<Func<PaymentCollection, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            var result = await _context.Set<PaymentCollection>()
                .Include(x => x.Recharges)
                .FirstOrDefaultAsync(funcWhere);
            return result;
        }

        /// <summary>
        /// 确认收款
        /// </summary>
        public async Task<bool> ConfirmAsync(string tradeNo, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            //检查收款单
            var model = await _context.Set<PaymentCollection>()
                .Include(x => x.SitePayment)
                .Include(x => x.Recharges)
                .FirstOrDefaultAsync(x => x.TradeNo == tradeNo);
            if (model == null)
            {
                throw new ResponseException("订单不存在或已删除");
            }
            //如果已经支付则直接返回
            if (model.Status == 2)
            {
                return true;
            }
            //如果已取消则不能支付
            if (model.Status == 3)
            {
                throw new ResponseException("订单已取消无法确认收款");
            }
            //查找会员账户
            var memberModel = await _context.Set<Members>()
                .Include(x => x.Group)
                .FirstOrDefaultAsync(x => x.UserId == model.UserId);
            if (memberModel == null)
            {
                throw new ResponseException("会员账户不存在或已删除");
            }
            //判断收款类型，如果是充值订单
            if (model.TradeType != 1)
            {
                throw new ResponseException("收款类型有误，请重试");
            }
            if (model.Recharges.Count == 0)
            {
                throw new ResponseException("没有找到充值订单，请重试");
            }

            memberModel.Amount += model.PaymentAmount;//增加余额
            //检查有无可升级的会员组
            if (memberModel.Group != null)
            {
                //条件筛选并排序，返回第一条
                var upgradeGroupModel = await _context.Set<MemberGroup>().OrderByBatch("-Amount")
                    .FirstOrDefaultAsync(x => x.Id != memberModel.Group.Id && x.IsUpgrade == 1 && x.Amount <= model.PaymentAmount);
                if (upgradeGroupModel != null && upgradeGroupModel.Amount >= memberModel.Group.Amount)
                {
                    memberModel.GroupId = upgradeGroupModel.Id;//升级会员组
                }
            }
            //更改订单状态
            model.Status = 2;
            model.CompleteTime = DateTime.Now;

            //添加消费记录
            await _context.Set<MemberAmountLog>().AddAsync(new MemberAmountLog()
            {
                UserId = model.UserId,
                Value = model.PaymentAmount,
                Remark = $"在线充值，充值交易号:{model.TradeNo}",
                AddTime = DateTime.Now
            });
            //更新会员
            _context.Set<Members>().Update(memberModel);
            //更新收款单
            _context.Set<PaymentCollection>().Update(model);
            //保存到数据库
            return await this.SaveAsync();
        }

        /// <summary>
        /// 取消收款
        /// </summary>
        public async Task<bool> CancelAsync(Expression<Func<PaymentCollection, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            //检查收款单
            var model = await _context.Set<PaymentCollection>().FirstOrDefaultAsync(funcWhere);
            if (model == null)
            {
                throw new ResponseException("交易记录不存在或已删除");
            }
            //如果已经付款或取消
            if (model.Status == 2)
            {
                throw new ResponseException("交易已经付款，无法进行取消");
            }
            if (model.Status == 3)
            {
                throw new ResponseException("交易已经取消，无法重复操作");
            }
            //修改收款状态
            model.Status = 3;
            model.CompleteTime = DateTime.Now;
            _context.Set<PaymentCollection>().Update(model);
            //保存到数据库
            return await this.SaveAsync();
        }

        /// <summary>
        /// 根据条件删除记录
        /// </summary>
        public async Task<bool> DeleteAsync(Expression<Func<PaymentCollection, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            var list = await _context.Set<PaymentCollection>()
                .Include(x => x.Recharges)
                .Where(funcWhere).ToListAsync();
            if (list == null)
            {
                return false;
            }
            foreach (var modelt in list)
            {
                _context.Set<PaymentCollection>().Attach(modelt);
            }
            _context.Set<PaymentCollection>().RemoveRange(list);
            return await this.SaveAsync();
        }

        /// <summary>
        /// 修改支付方式(客户)
        /// </summary>
        public async Task<bool> PayAsync(PaymentCollectionEditDto modelDto, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            //获取当前登录用户
            var userId = await _userService.GetUserIdAsync();
            //根据ID获取记录
            var model = await _context.Set<PaymentCollection>()
                .FirstOrDefaultAsync(x => x.Id == modelDto.Id && x.UserId == userId
                    && DateTime.Compare(x.StartTime, DateTime.Now) <= 0);
            //如果不存在则抛出异常
            if (model == null)
            {
                throw new ResponseException("交易单号有误或已过期");
            }
            //判断支付方式是否改变
            if (model.PaymentId == modelDto.PaymentId)
            {
                return true;
            }
            //判断是否已支付
            if (model.Status != 1)
            {
                throw new ResponseException("订单已支付或已取消，无法更改支付方式");
            }
            //查询支付方式
            var paymentModel = await _context.Set<SitePayment>().FirstOrDefaultAsync(x => x.Id == modelDto.PaymentId);
            if (paymentModel == null)
            {
                throw new ResponseException("支付方式有误，请确认后操作");
            }
            //再次支付不允许线下支付
            if (paymentModel.Type == "cash")
            {
                throw new ResponseException("交易无法更换线下支付，请重试");
            }
            model.PaymentId = paymentModel.Id;
            model.PaymentTitle = paymentModel.Title;
            _context.Set<PaymentCollection>().Update(model);
            //保存到数据库
            return await this.SaveAsync();
        }

        /// <summary>
        /// 获取收款总数量
        /// </summary>
        public async Task<int> QueryCountAsync(Expression<Func<PaymentCollection, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            return await _context.Set<PaymentCollection>().Where(funcWhere).CountAsync();
        }

        /// <summary>
        /// 获取收款总金额
        /// </summary>
        public async Task<decimal> QueryAmountAsync(Expression<Func<PaymentCollection, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            var result = await _context.Set<PaymentCollection>()
                .Where(funcWhere).OrderByDescending(x => x.AddTime)
                .GroupBy(x => new { x.AddTime.Month, x.AddTime.Day })
                .Select(g => g.Sum(x => x.PaymentAmount)).FirstOrDefaultAsync();
            return result;
        }
    }
}
